import time
from flask import current_app
from flask import g
from flask import request
from flask_restful import inputs
from flask_restful.reqparse import RequestParser
from flask_restful import Resource
from flask import abort

from cache.article import ArticleDetailCache
from cache.user import UserProfileCache, UserFollowingCache, UserArticleAttiudeCache, UserCollectionCache, \
    UserHistoryCache
from models.news import Attitude, Collection
from models.user import Relation
from toutiao import db
from toutiao.utils.decorators import loginrequired


# 详情页展示
class DetailResource(Resource):
    def get(self, article_id):
        # # 1.根据文章id查询文章详情
        # article = Article.query.filter_by(id=article_id, status=Article.STATUS.APPROVED).first()
        # if article is None:
        #     abort(404)  # 类似return
        # article_dict = marshal(article, article_fields)
        #
        # # 2 获取作者信息
        # aut_info = UserProfileCache(article_dict['aut_id']).get()
        # article_dict['aut_name'] = aut_info['name']
        # article_dict['aut_photo'] = aut_info['photo']

        article_dict = ArticleDetailCache(article_id).get()

        if article_dict is None:
            abort(404)
        # 3 初始化,是否关注, 是否喜欢,是否收藏
        is_followed = False  # 关注
        attitude = None  # 喜欢
        is_collected = False  # 收藏
        if g.user_id:
            # attitudes = UserArticleAttiudeCache(g.user_id).all_articles_attitude()
            # 从字典attitudes中拿数据
            # attitude=attitudes.get(int(article_id))
            # 获取单个文章的状态
            attitude = UserArticleAttiudeCache(g.user_id).get_article_attitude(article_id)

            # 1.先把所有的收藏数据(文章id)，获取
            total_count, article_ids = UserCollectionCache(g.user_id).get(1, -1)
            # 2.然后我们再判断
            is_collected = int(article_id) in article_ids

            #  添加历史记录
            UserHistoryCache(g.user_id).add(article_id)

        article_dict['is_followed'] = is_followed
        article_dict['attitude'] = attitude
        article_dict['is_collected'] = is_collected
        # 更新所有文章的缓存
        UserArticleAttiudeCache(g.user_id).clear()
        # 4 返回相应
        return article_dict


# 关注
class UserFllowing(Resource):
    # 关注是用户操作需要登陆
    method_decorators = [loginrequired]

    def post(self):

        # 1.接收数据  一开始用reqparse.RequestParser()写,发现用了4行代码,而且还不太熟练,就换回来了
        # parse = reqparse.RequestParser()
        # parse.add_argument('target', location='json', required=True)
        # args = parse.parse_args()
        # user = User.query.get(args.get('target'))

        target = request.json.get('target')
        # 2.验证数据
        user = UserProfileCache(target).get()
        if user is None:
            return {'message': '没有这个人'}, 400
        # 3.数据入库
        # 判断下之前否有关注过
        data = Relation.query.filter_by(user_id=g.user_id, target_user_id=target).first()
        try:
            if data is None:
                relation = Relation()
                relation.user_id = g.user_id  # 当前登陆用户
                relation.target_user_id = target
                relation.relation = Relation.RELATION.FOLLOW
                db.session.add(relation)

            else:
                data.relation = Relation.RELATION.FOLLOW
        except Exception as e:
            current_app.logger.error(e)
        db.session.commit()
        # 添加缓存
        UserFollowingCache(g.user_id).update(target, time.time())

        # 4.返回相应
        return {'target': target}, 201

    # 用户关注列表
    def get(self):
        # 获取分页
        page = request.args.get('page', 1)
        per_page = request.args.get('per_page', 10)
        try:
            page = int(page)
            per_page = int(per_page)
        except Exception:
            page = 1
            per_page = 10
        # # 查询获取所有关注人员列表
        # relations = Relation.query.filter_by(user_id=g.user_id, relation=Relation.RELATION.FOLLOW).order_by(
        #     Relation.utime.desc()).all()
        # # 所有关注数
        # total_count = len(relations)
        # # 关注人的id      列表推导式
        # target_user_ids = [relation.target_user_id for relation in relations]

        # 调用缓存
        target_user_ids = UserFollowingCache(g.user_id).get()
        total_count = len(target_user_ids)

        # 对数据进行分页
        page_target_user_ids = target_user_ids[(page - 1) * per_page:page * per_page]
        # 对分页数据遍历，并获信息
        data_list = []
        for user_id in page_target_user_ids:
            user = UserProfileCache(user_id).get()
            data_list.append({
                'id': user_id,
                'name': user.get('name'),
                'photo': user.get('photo'),
                'mutual_follow': False  # 是否相互关注
            })
        UserFollowingCache(g.user_id).clear()
        # 响应数据
        return {'total_count': total_count, 'page': page, 'per_page': per_page, 'results': data_list}


# 取消关注
class UserFollowingDelete(Resource):
    # 同上登陆用户才可以进行的操作
    method_decorators = [loginrequired]

    def delete(self, target):
        # 取消关注和加添类似
        # 查询出来之后,修改用户的关注状态就行,同时清除缓存
        # 小逻辑,进行数据库操作可以进行try,提高代码的健壮性
        try:
            Relation.query.filter_by(user_id=g.user_id, target_user_id=target).update(
                {'relation': Relation.RELATION.DELETE}
            )
        except Exception as e:
            current_app.lagger.error(e)
            return {'message': '数据库异常'}, 507
        db.session.commit()

        # 清除缓存
        UserFollowingCache(g.user_id).update(target, time.time(), -1)

        return {'message': 'ok'}, 204


# 点赞
class ArticleLiking(Resource):
    # 逻辑与关注类似
    method_decorators = [loginrequired]

    # 不过改成用户对那篇文章的操作
    def post(self):
        # 1 接受参数并校验
        parser = RequestParser()
        parser.add_argument('target', type=int, required=True, location='json')
        args = parser.parse_args()
        target = args.target
        # 2查询用户是否有过记录
        try:
            atti = Attitude.query.filter_by(user_id=g.user_id, article_id=target).first()
            if atti:
                # 如果有态度，更新态度的值
                atti.attitude = Attitude.ATTITUDE.LIKING
            # 没有
            else:
                atti = Attitude(user_id=g.user_id, article_id=target, attitude=Attitude.ATTITUDE.LIKING)
                db.session.add(atti)
        except Exception as e:
            current_app.logger.error(e)
        # 保存数据
        db.session.commit()
        # 更新单条缓存数据
        UserArticleAttiudeCache(g.user_id).update_field(target, Attitude.ATTITUDE.LIKING)
        # 3返回数据
        return {'target': target}, 201


# 取消点赞
class ArticleLikingDelete(Resource):
    method_decorators = [loginrequired]

    def delete(self, target):
        # 逻辑删除,修改状态就可以的
        # 通过用户id和文章id来查询,然后修改状态,并保存就行    1是点赞,非1就不是赞了  (看模型状态码)
        Attitude.query.filter_by(user_id=g.user_id, article_id=target).update({'attitude': 3})
        db.session.commit()

        # 更新单条缓存数据
        UserArticleAttiudeCache(g.user_id).update_field(target, -1)
        # 返回响应
        return {'message': 'ok'}, 204


# 不喜欢的文章
class ArticleDislike(Resource):
    method_decorators = [loginrequired]

    # 不喜欢 逻辑和代码同点赞
    def post(self):
        # 1 接受参数并校验
        parser = RequestParser()
        parser.add_argument('target', type=int, required=True, location='json')
        args = parser.parse_args()
        target = args.target
        # 2查询用户是否有过记录
        try:
            atti = Attitude.query.filter_by(user_id=g.user_id, article_id=target).first()
            if atti:
                # 如果有状态，更新状态的值
                atti.attitude = Attitude.ATTITUDE.DISLIKE
            # 没有
            else:
                atti = Attitude(user_id=g.user_id, article_id=target, attitude=Attitude.ATTITUDE.DISLIKE)
                db.session.add(atti)
        except Exception as e:
            current_app.logger.error(e)

        # 保存数据
        db.session.commit()
        # 缓存单条数据
        UserArticleAttiudeCache(g.user_id).update_field(target, Attitude.ATTITUDE.DISLIKE)
        # 3返回数据
        return {'target': target}, 201


# 取消不喜欢
class ArticleDisLikeDelete(Resource):
    method_decorators = [loginrequired]

    def delete(self, target):
        # 逻辑删除,修改状态就可以的
        # 通过用户id和文章id来查询,然后修改状态,并保存就行    0是不喜欢,非0就取消  (看模型状态码)
        Attitude.query.filter_by(user_id=g.user_id, article_id=target).update({'attitude': 3})
        db.session.commit()

        # 缓存单条数据
        UserArticleAttiudeCache(g.user_id).update_field(target, -1)
        # 返回响应
        return {'message': 'ok'}, 204


# 收藏
class CollectionResource(Resource):
    method_decorators = [loginrequired]

    def post(self):
        # 接受和校验参数
        parser = RequestParser()
        parser.add_argument('target', type=int, location='json', required=True)
        args = parser.parse_args()
        target = args.target
        # 查询用户是否有过收藏
        collection = Collection.query.filter_by(user_id=g.user_id, article_id=target).first()

        if collection:
            collection.is_deleted = False
        else:
            collection = Collection(user_id=g.user_id, article_id=target, is_deleted=False)
            db.session.add(collection)
        # 保存数据
        db.session.commit()
        UserCollectionCache(g.user_id).clear()
        # 响应结果
        return {'target': target}, 201

    def get(self):
        """
        1.必须是登陆用户才可以获取收藏数据
        2.为了缓存，我们是把所有收藏数据查询出来（简单查询）
        3.对收藏的数据进行遍历，来获取收藏的文章id
        4.分页获取指定的文章id列表
        5.遍历文章id列表来获取文章信息
        6.返回相应
        """
        # 1.必须是登陆用户才可以获取收藏数据

        page = request.args.get('page', 1)
        per_page = request.args.get('per_page', 2)

        try:
            # 转换类型,有异常设为默认值
            page = int(page)
            per_page = int(per_page)
        except Exception:
            page = 1
            per_page = 2

        # 2 查询所有收藏数据
        # collections = Collection.query.filter_by(user_id=g.user_id, is_deleted=False).order_by(Collection.utime.desc()).all()
        # article_ids = []
        # total_count = len(collections)
        # # 3.遍历数据获取文章的id
        # for collection in collections:
        #     article_ids.append(collection.article_id)
        # # 4.分页获取指定的文章id列表  切割数据
        # page_article_ids = article_ids[(page - 1) * per_page:page * per_page]

        # 调用缓存
        total_count, page_article_ids = UserCollectionCache(g.user_id).get(page, per_page)
        # 5.遍历文章id列表来获取文章信息
        restuls = []
        from cache.article import ArticleDetailCache
        for article_id in page_article_ids:
            article = ArticleDetailCache(article_id).get()
            restuls.append(article)

        UserCollectionCache(g.user_id).clear()
        # 6.返回相应
        return {'page': page, 'per_page': per_page, 'results': restuls, 'total_count': total_count}


# 取消收藏
class CollectDelete(Resource):
    method_decorators = [loginrequired]

    def delete(self, target):
        # 根据用户和文章找到对应的收藏文章  更新标记即可
        Collection.query.filter_by(user_id=g.user_id, article_id=target).update({'is_deleted': True})
        db.session.commit()
        UserCollectionCache(g.user_id).clear()
        return {'message': 'ok'}, 204
